var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

//题目的数据模型


/***
 * 选项
 */
export var Option = //是否选中


/**
 * 构造函数
 * @param content : any     选项的内容
 * @param id : any     选项的标识符，在一个题目中，需要唯一
 * @param choiceQuestion : ChoiceQuestion   选择所属的题目
 */
//选项的内容
function Option(content, id, choiceQuestion) {
    _classCallCheck(this, Option);

    this.content = content;
    this.id = id;
    this.choiceQuestion = choiceQuestion;
} //选择所属的题目
//选项的标识符，在一个题目中，需要唯一
;

/***
 * 选择约束类
 */
export var ChoiceCondition = function () {
    //最大选择数目

    /**
     * 构造函数
     * @param minSelectCount : number     最小选择数目
     * @param maxSelectCount : number     最大选择数目
     */
    function ChoiceCondition(minSelectCount, maxSelectCount) {
        _classCallCheck(this, ChoiceCondition);

        this._minSelectCount = 0;
        this._maxSelectCount = 1;

        this.minSelectCount = minSelectCount;
        this.maxSelectCount = maxSelectCount;
    }

    /* 
    @property @计算 @读写 minSelectCount : number   最小选择数目
    */
    //最小选择数目


    _createClass(ChoiceCondition, [{
        key: "minSelectCount",
        get: function get() {
            return this._minSelectCount;
        },
        set: function set(value) {
            if (value > this._maxSelectCount) {
                tihs._maxSelectCount = value;
            }

            this._minSelectCount = value;
        }

        /* 
        @property @计算 @读写 maxSelectCount : number   最大选择数目
        */

    }, {
        key: "maxSelectCount",
        get: function get() {
            return this._maxSelectCount;
        },
        set: function set(value) {
            if (value < this._minSelectCount) {
                tihs._minSelectCount = value;
            }

            this._maxSelectCount = value;
        }

        /* 
        @property @计算 @只读 requisite : boolean   是否必须选择
        */

    }, {
        key: "requisite",
        get: function get() {
            return this.minSelectCount > 0;
        }

        /* 
        @property @计算 @只读 multiselect : boolean   是否多选
        */

    }, {
        key: "multiselect",
        get: function get() {
            return this.maxSelectCount == 1;
        }
    }]);

    return ChoiceCondition;
}();

/***
 * 选择题
 */
export var ChoiceQuestion = function (_ChoiceCondition) {
    _inherits(ChoiceQuestion, _ChoiceCondition);

    //题目的分值


    /**
     * 构造函数
     * @param subject : any     选择题的问题、标题；
     * @param minSelectCount : number 最小选择数目
     * @param maxSelectCount : number 最大选择数目
     * @param id : any   题目的唯一标识符
     * @param options : Array<Option> = []  盛装选择题的所有选项的数组
     * @param rightAnswerIds : Array = []  盛装正确答案id的数组
     * @param defaultSelectedIds : Array = []  盛装默认选中的答案id的数组
     * @param scoreValuel : number = 1    题目的分值
     * @param type : any    题目类型
     */
    //盛装正确答案id的数组
    //选择题的问题、标题；
    //题目类型
    function ChoiceQuestion(subject, minSelectCount, maxSelectCount, id) {
        var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
        var rightAnswerIds = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : [];
        var defaultSelectedIds = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : [];
        var scoreValuel = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
        var type = arguments[8];

        _classCallCheck(this, ChoiceQuestion);

        var _this = _possibleConstructorReturn(this, (ChoiceQuestion.__proto__ || Object.getPrototypeOf(ChoiceQuestion)).call(this, minSelectCount, maxSelectCount));

        _this.subject = subject;
        _this.options = options;
        _this.id = id;
        _this.type = type;
        _this.rightAnswerIds = rightAnswerIds;
        _this.defaultSelectedIds = defaultSelectedIds;
        _this.scoreValuel = scoreValuel;

        return _this;
    }

    /* 
    @property @计算 @读写 options : [Option]   盛装选择题的所有选项的数组
    */
    //盛装默认选中的答案id的数组
    //盛装选择题的所有选项的数组
    //题目的唯一标识符


    _createClass(ChoiceQuestion, [{
        key: "selectOptionOfId",


        /**
         * 选中 id 为 optionID 的选项
         * @param optionID : any  需要被选中的选项的id
         */
        value: function selectOptionOfId(optionID) {
            this.options.forEach(function (option) {
                if (option.id === optionID) {
                    option.selected = true;
                }
            });
        }

        /**
         * 选中 idList 中指定的所有 选项
         * @param idList : Array  需要被选中的选项的id数组
         */

    }, {
        key: "selectOptionsOfIdList",
        value: function selectOptionsOfIdList(idList) {
            this.options.forEach(function (option) {
                if (idList.includes(option.id)) {
                    option.selected = true;
                }
            });
        }

        /**
         * 只选中 idList 中指定的所有 选项
         * @param idList : Array  需要被选中的选项的id数组
         */

    }, {
        key: "onlySelectOptionsOfIdList",
        value: function onlySelectOptionsOfIdList(idList) {
            this.options.forEach(function (option) {
                if (idList.includes(option.id)) {
                    option.selected = true;
                } else {
                    option.selected = false;
                }
            });
        }

        /**
         * 只选中除 idList 中指定的 之外的 所有选项
         * @param idList : Array  需要被排除选中的选项的id数组
         */

    }, {
        key: "onlySelectOptionsOutofIdList",
        value: function onlySelectOptionsOutofIdList(idList) {
            this.options.forEach(function (option) {
                if (idList.includes(option.id)) {
                    option.selected = false;
                } else {
                    option.selected = true;
                }
            });
        }

        /**
         * 取消选中 id 为 optionID 的选项
         * @param optionID : any  需要被取消选中的选项的id
         */

    }, {
        key: "deselectOptionOfId",
        value: function deselectOptionOfId(optionID) {
            this.options.forEach(function (option) {
                if (option.id === optionID) {
                    option.selected = false;
                }
            });
        }

        /**
         * 取消选中 idList 中指定的所有 选项
         * @param idList : Array  需要被取消选中的选项的id数组
         */

    }, {
        key: "deselectOptionsOfIdList",
        value: function deselectOptionsOfIdList(idList) {
            this.options.forEach(function (option) {
                if (idList.includes(option.id)) {
                    option.selected = false;
                }
            });
        }

        /**
         * 取消所有选项的选中
         */

    }, {
        key: "deselectAll",
        value: function deselectAll() {
            this.options.forEach(function (option) {
                option.selected = false;
            });
        }

        /**
         * 重围选中，重置后只选中默认选中的选项
         */

    }, {
        key: "resetSelect",
        value: function resetSelect() {
            this.onlySelectOptionsOfIdList(this.defaultSelectedIds);
        }

        //测试是否满足必须

    }, {
        key: "testRequisite",
        value: function testRequisite() {
            return !this.requisite || this.selectedOptions.length > 0;
        }

        //测试是否满足最小选择数

    }, {
        key: "testMinSelectCount",
        value: function testMinSelectCount() {
            return this.selectedOptions.length >= this.minSelectCount;
        }

        //测试是否满足最大选择数

    }, {
        key: "testMaxSelectCount",
        value: function testMaxSelectCount() {
            return this.selectedOptions.length <= this.maxSelectCount;
        }

        //测试是否满足所有的约束条件

    }, {
        key: "testAllCondition",
        value: function testAllCondition() {
            return this.testRequisite() && this.testMinSelectCount() && this.testMaxSelectCount();
        }

        //测试是否回答正确，需要设置 rightAnswerIds

    }, {
        key: "testAnswer",
        value: function testAnswer() {

            var selectedIDs = this.selectedOptions.map(function (option) {
                return option.id;
            });

            var rightIDs = this.rightAnswerIds;

            var selectedsIsAllRight = this.selectedIDs.every(function (seleId) {

                var haveId = rightIDs.includes(seleId);

                rightIDs = rightIDs.filter(function (rightId) {
                    return rightId !== seleId;
                });

                return haveId;
            });

            var rightIsAllSelected = rightIDs.length == 0;

            return selectedsIsAllRight && rightIsAllSelected;
        }

        /**
         * 返回 id 为 optionID 的 选项 在 options 中的索引；如果没有符合条件的元素返回 -1
         * @param optionID : any 被查找的选项的id
         */

    }, {
        key: "findIndexForId",
        value: function findIndexForId(optionID) {
            return this.options.findIndex(function (option) {
                return option.id === optionID;
            });
        }

        /**
         * 返回 id 为 optionID 的 选项 ；如果没有符合条件的元素返回 undefined
         * @param optionID : any 被查找的选项的id
         */

    }, {
        key: "findOptionForId",
        value: function findOptionForId(optionID) {
            return this.options.find(function (option) {
                return option.id === optionID;
            });
        }

        /**
         * 返回 idList 中的 id 对应的 选项 在 options 中的索引的数组；
         * @param idList : Array 被查找的选项的id列表
         */

    }, {
        key: "findIndexListForIdList",
        value: function findIndexListForIdList(idList) {
            var optionList = this.findOptionListForIdList(idList);
            return this._getOptionIds(optionList);
        }

        /**
         * 返回 idList 中的 id 对应的 选项 的数组；
         * @param idList : Array 被查找的选项的id列表
         */

    }, {
        key: "findOptionListForIdList",
        value: function findOptionListForIdList(idList) {
            return this.options.filter(function (option) {
                return idList.includes(option.id);
            });
        }

        /**
         * 删除 id 为 optionID 的 选项 ；
         * @param optionID : any 被删除的选项的id
         */

    }, {
        key: "deleteOptionForId",
        value: function deleteOptionForId(optionID) {
            this.options.forEach(function (option, index, arr) {
                if (option.id === optionID) {
                    arr.splice(index, 1);
                }
            });
        }

        /**
         * 删除 idList 中指定的所有选项 ；
         * @param idList : Array 被删除的选项的id列表
         */

    }, {
        key: "deleteOptionForIdList",
        value: function deleteOptionForIdList(idList) {
            this.options.forEach(function (option, index, arr) {
                if (idList.includes(option.id)) {
                    arr.splice(index, 1);
                }
            });
        }

        /**
         * 获得数组 questionList 内所有问题的id
         * 
         * @param questionList : [ChoiceQuestion] 问题的数组
         * @returns Array   questionList内所有问题的id
         */

    }, {
        key: "_getOptionIds",
        value: function _getOptionIds(optionList) {
            return optionList.map(function (option) {
                return option.id;
            });
        }
    }, {
        key: "options",
        get: function get() {
            return this._options;
        },
        set: function set(value) {
            if (value && value.length > 0) {
                value.forEach(function (element) {
                    element.choiceQuestion = this;
                }, this);
            }

            this._options = value;
        }

        /* 
        @property @计算 @读写 defaultSelectedIds : Array   默认选中的选项的id数组
        */

    }, {
        key: "defaultSelectedIds",
        get: function get() {
            return this._defaultSelectedIds;
        },
        set: function set(value) {
            this.defaultSelectedIds.forEach(function (optionID) {
                this.selectOptionOfId(optionID);
            }, this);
            this._defaultSelectedIds = value;
        }

        /* 
        @property @计算 @只读 selectedOptions : [Option]   获得所有被选中的选项
        */

    }, {
        key: "selectedOptions",
        get: function get() {
            return this.options.filter(function (option, index) {
                return option.selected;
            });
        }

        /* 
        @property @计算 @只读 selectedOptionIds : Array   获得所有被选中的选项的id
        */

    }, {
        key: "selectedOptionIds",
        get: function get() {
            return this.selectedOptions.map(function (option) {
                return option.id;
            });
        }

        /* 
        @property @计算 @只读 score : number  回答本题得的分数
        */

    }, {
        key: "score",
        get: function get() {
            return this.testAnswer() ? this.scoreValuel : 0;
        }
    }]);

    return ChoiceQuestion;
}(ChoiceCondition);

/***
 * 问题列表
 */
export var ChoiceQuestionList = function (_Array) {
    _inherits(ChoiceQuestionList, _Array);

    function ChoiceQuestionList() {
        _classCallCheck(this, ChoiceQuestionList);

        return _possibleConstructorReturn(this, (ChoiceQuestionList.__proto__ || Object.getPrototypeOf(ChoiceQuestionList)).apply(this, arguments));
    }

    _createClass(ChoiceQuestionList, [{
        key: "_getQuestionIds",


        /**
         * 获得数组 questionList 内所有问题的id
         * 
         * @param questionList : [ChoiceQuestion] 问题的数组
         * @returns Array   questionList内所有问题的id
         */
        value: function _getQuestionIds(questionList) {
            return questionList.map(function (question) {
                return question.id;
            });
        }

        //测试是否每一个题目都符合约束

    }, {
        key: "testEveryAccordCondition",
        value: function testEveryAccordCondition() {
            return this.every(function (question, index) {
                return question.testAllCondition();
            });
        }

        //测试是否有部分题目符合约束

    }, {
        key: "testSomeAccordCondition",
        value: function testSomeAccordCondition() {
            return this.some(function (question, index) {
                return question.testAllCondition();
            });
        }

        //测试是否每个题目都回答正确

    }, {
        key: "testEveryIsRight",
        value: function testEveryIsRight() {
            return this.every(function (question) {
                return question.testAnswer();
            });
        }

        //测试是否部分题目回答正确

    }, {
        key: "testSomeIsRight",
        value: function testSomeIsRight() {
            return this.some(function (question) {
                return question.testAnswer();
            });
        }

        /**
         * 取消所有题目的选中
         */

    }, {
        key: "deselectAll",
        value: function deselectAll() {
            this.forEach(function (question) {
                question.deselectAll();
            });
        }

        /**
         * 重围所有题目的选中，重置后每个题目只选中默认选中的选项
         */

    }, {
        key: "resetSelect",
        value: function resetSelect() {
            this.forEach(function (question) {
                question.resetSelect();
            });
        }

        /**
         * 返回 id 为 questionID 的 选择题 在 选择题组 中的索引；如果没有符合条件的元素返回 -1
         * @param questionID : any 被查找的选择题的id
         */

    }, {
        key: "findIndexForId",
        value: function findIndexForId(questionID) {
            return this.findIndex(function (question) {
                return question.id === questionID;
            });
        }

        /**
         * 返回 id 为 questionID 的 选择题；如果没有符合条件的元素返回 undefined
         * @param questionID : any 被查找的选择题的id
         */

    }, {
        key: "findQuestionForId",
        value: function findQuestionForId(questionID) {
            return this.find(function (question) {
                return question.id === questionID;
            });
        }

        /**
         * 返回 idList 中的 id 对应的 选择题 在 选择题组 中的索引的数组；
         * @param idList : Array 被查找的选择题的id列表
         */

    }, {
        key: "findIndexListForIdList",
        value: function findIndexListForIdList(idList) {
            var questionList = this.findQuestionListForIdList(idList);
            return this._getQuestionIds(questionList);
        }

        /**
         * 返回 idList 中的 id 对应的 选择题 的数组；
         * @param idList : Array 被查找的选择题的id列表
         */

    }, {
        key: "findQuestionListForIdList",
        value: function findQuestionListForIdList(idList) {
            return this.filter(function (question) {
                return idList.includes(question.id);
            });
        }

        /**
         * 删除 id 为 questionID 的 选择题；
         * @param questionID : any 被删除的选择题的id
         */

    }, {
        key: "deleteQuestionForId",
        value: function deleteQuestionForId(questionID) {
            this.forEach(function (question, index, arr) {
                if (question.id === questionID) {
                    arr.splice(index, 1);
                }
            });
        }

        /**
         * 删除 idList 中指定的所有选择题 ；
         * @param idList : Array 被删除的选择题的id列表
         */

    }, {
        key: "deleteQuestionForIdList",
        value: function deleteQuestionForIdList(idList) {
            this.forEach(function (question, index, arr) {
                if (idList.includes(question.id)) {
                    arr.splice(index, 1);
                }
            });
        }
    }, {
        key: "passConditionOfQuestions",


        /* 
        @property @计算 @只读 passConditionOfQuestions : [ChoiceQuestion]   获得符合约束条件的所有题目的列表
        */
        get: function get() {
            return this.filter(function (question, index) {
                return question.testAllCondition();
            });
        }

        /* 
        @property @计算 @只读 passConditionOfQuestionIds : Array   获得符合约束条件的所有题目的id列表
        */

    }, {
        key: "passConditionOfQuestionIds",
        get: function get() {
            return this._getQuestionIds(this.passConditionOfQuestions);
        }

        /* 
        @property @计算 @只读 notPassConditionOfQuestions : [ChoiceQuestion]   获得不符合约束条件的所有题目的列表
        */

    }, {
        key: "notPassConditionOfQuestions",
        get: function get() {
            return this.filter(function (question, index) {
                return !question.testAllCondition();
            });
        }

        /* 
        @property @计算 @只读 notPassConditionOfQuestionIds : Array   获得不符合约束条件的所有题目的id列表
        */

    }, {
        key: "notPassConditionOfQuestionIds",
        get: function get() {
            return this._getQuestionIds(this.notPassConditionOfQuestions);
        }

        /* 
        @property @计算 @只读 answerRightQuestions : [ChoiceQuestion]   获得回答正确的题目的列表
        */

    }, {
        key: "answerRightQuestions",
        get: function get() {
            return this.filter(function (question) {
                return question.testAnswer();
            });
        }

        /* 
        @property @计算 @只读 answerRightQuestionIds : Array   获得回答正确的题目的id
        */

    }, {
        key: "answerRightQuestionIds",
        get: function get() {
            return this._getQuestionIds(this.answerRightQuestions);
        }

        /* 
        @property @计算 @只读 answerWrongQuestions : [ChoiceQuestion]   获得回答错误的题目的列表
        */

    }, {
        key: "answerWrongQuestions",
        get: function get() {
            return this.filter(function (question) {
                return !question.testAnswer();
            });
        }

        /* 
        @property @计算 @只读 answerWrongQuestionIds : Array   获得回答错误的题目的id
        */

    }, {
        key: "answerWrongQuestionIds",
        get: function get() {
            return this._getQuestionIds(this.answerWrongQuestions);
        }

        /* 
        @property @计算 @只读 totalScore : number   所有题目的得分总和
        */

    }, {
        key: "totalScore",
        get: function get() {
            return this.reduce(function (total, currentQuestion) {
                return total + currentQuestion.score;
            }, 0);
        }
    }]);

    return ChoiceQuestionList;
}(Array);